package com.fxc.crowd.util;


import com.fxc.crowd.aliyun.api.HttpUtils;
import com.fxc.crowd.constant.CrowdConstant;

import com.obs.services.ObsClient;
import com.obs.services.model.PutObjectRequest;
import com.obs.services.model.PutObjectResult;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import static com.fxc.crowd.constant.CrowdConstant.MAIL_FAIL_TEMPLATE;
import static com.fxc.crowd.constant.CrowdConstant.MAIL_HEAD_TEMPLATE;

/**
 * 项目通用的方法类
 * @author FDL
 */
public class CrowdUtil {


    /**
     * 专门负责上传文件到OSS服务器的工具方法
     * @param endPoint 为桶所在区域对应的终端节点地址，可以在桶的基本信息处获取
     * @param ak Access Key Id（AK）：访问密钥ID。与私有访问密钥关联的唯一标识符；访问密钥ID和私有访问密钥一起使用，对请求进行加密签名。
     * @param sk Secret Access Key（SK）：与访问密钥ID结合使用的私有访问密钥，对请求进行加密签名，可标识发送方，并防止请求被修改。
     * @param inputStream 网络流
     * @param bucketName 为OBS中待处理图片存放的桶名。
     * @param originalName 为存储在OBS上bucketName桶下的原图片名称，后缀名必须为图片处理支持的图片格式。
     * @return
     */
    public static ResultEntity<String> uploadFileToObs(String endPoint, String ak, String sk, InputStream inputStream, String bucketName, String originalName){
//        String endPoint = "https://your-endpoint";
//        String ak = "*** Provide your Access Key ***";
//        String sk = "*** Provide your Secret Key ***";

        // 创建ObsClient实例
        ObsClient obsClient = new ObsClient(ak, sk, endPoint);

        // 生成上传文件的目录
        String folderName = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));

        // 生成上传文件在OSS服务器上保存时的文件名
        // 使用UUID生成文件主体名称
        String fileMainName = UUID.randomUUID().toString().replace("-", "");

        // 从原始文件获得文件扩展名
        String extensionName = originalName.substring(originalName.lastIndexOf("."));

        // 使用目录、文件主体名称、文件扩展名称拼接得到对象名称
        String objectName = folderName + "/" + fileMainName + extensionName;

        try {
            // 待上传的本地文件路径，需要指定到具体的文件名

            PutObjectResult putObjectResult = obsClient.putObject(bucketName, objectName, inputStream);

            // 获取图片地址
            String objectUrl = putObjectResult.getObjectUrl();

            return ResultEntity.successWithData(objectUrl);
        } finally {
            if (obsClient != null) {
                try {
                    /*
                     * Close obs client
                     */
                    obsClient.close();
                } catch (IOException e) {
                }
            }
        }
        // 待上传的本地文件路径，需要指定到具体的文件名
//        FileInputStream fis2 = new FileInputStream(new File("localfile2"));
//        PutObjectRequest request = new PutObjectRequest();
//        request.setBucketName("bucketname");
//        request.setObjectKey("objectname2");
//        request.setInput(fis2);
//        obsClient.putObject(request);

    }

    /**
     * 对明文字符串进行md5加密
     * @param source 传入的明文字符串
     * @return 加密的结果
     */
    public static String md5(String source){

        // 1.判断resource是否有效
        if (source == null || source.length() == 0){
            // 2.如果不是有效的字符串抛出异常
            throw new RuntimeException(CrowdConstant.MESSAGE_STRING_INVALIDATE);
        }


        try {
            // 3.获取MessageDigest对象
            String algorithm = "md5";
            MessageDigest messageDigest = MessageDigest.getInstance(algorithm);

            // 4.获取明文字符串对应的字节数组
            byte[] input = source.getBytes();

            // 5.执行加密
            byte[] output = messageDigest.digest(input);

            // 6.创建BigInteger对象
            int sigNum = 1;
            BigInteger bigInteger = new BigInteger(sigNum, output);

            // 7.按照16进制bigInteger的值转换为字符串
            int radix = 16;
            String encoded = bigInteger.toString(radix).toUpperCase()   ;

            return encoded;

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }


        return null;
    }

    /**
     * 判断当前请求是否为AJAX请求
     * @param request
     * @return
     */
    public static boolean judegeRequestType(HttpServletRequest request){
        //1.获取请求消息请求头
        String accept = request.getHeader("Accept");
        String header = request.getHeader("X-Requested-With");

        //2.判断
        return (
                (accept != null && accept.equals("application/json"))
                ||
                (header != null && header.equals("XMLHttpRequest"))
        );
    }

    /**
     * @param host     短信接口调用的URL地址
     * @param path     具体发送短信功能的地址
     * @param method   请求方法
     * @param phoneNum 接收验证码的手机
     * @param appCode  阿里云云市场里面的AppCode
     * @param sign     测试使用 1
     * @param skin     测试使用 1
     *                 返回结果 ：200 正常；400 URL无效；401 appCode错误； 403 次数用完； 500 API网管错误
     */
    public static ResultEntity<String> sendShortMessage(String host, String path, String method, String phoneNum, String appCode, String sign, String skin) {
        Map<String, String> headers = new HashMap<>();
        // 541707ddc9c8463eb9336c3bfc0624b3
        headers.put("Authorization", "APPCODE " + appCode);

        Map<String, String> querys = new HashMap<>();
        // 生成要发送的验证码
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            int random = (int) (Math.random() * 10);
            builder.append(random);
        }
        String code = builder.toString();
        querys.put("param", code);
        // 收短信的手机
        querys.put("phone", phoneNum);
        // 签名编号
        querys.put("sign", sign);
        // 模板编号
        querys.put("skin", skin);
        try {
            HttpResponse response = HttpUtils.doGet(host, path, method, headers, querys);
            //System.out.println(response.toString());如不输出json, 请打开这行代码，打印调试头部状态码。
            StatusLine statusLine = response.getStatusLine();
            // 获取状态码
            int statusCode = statusLine.getStatusCode();
            if (statusCode == 200) {
                return ResultEntity.successWithData(code);
            }
            return ResultEntity.failed(statusLine.getReasonPhrase());
        } catch (Exception e) {
            e.printStackTrace();
            return ResultEntity.failed(e.getMessage());
        }
    }

    /**
     * @param title  发送邮件的标题
     * @param signature 发送者的署名
     * @param appCode  QQ邮箱里面的16位STMP口令
     * @param receiver 接收人的邮箱
     * @param account  发送者者的QQ号
     *                 返回结果 ：200 正常；400 URL无效；401 appCode错误； 403 次数用完； 500 API网管错误
     */
    public static ResultEntity<String> sendShortMail(String title, String signature, String appCode, String account, String receiver) {
        // 生成要发送的验证码
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            int random = (int) (Math.random() * 10);
            builder.append(random);
        }
        String code = builder.toString();

        String Mails[] = {account};

        String Secret[] = {appCode};

        String html = MAIL_HEAD_TEMPLATE + code  + MAIL_FAIL_TEMPLATE;

        QQMail m=new QQMail(signature,Mails,Secret);

        m.sendQQMail(title, html ,receiver);

        return ResultEntity.successWithData(code);

    }


}
